const mor = require("./mongoHelper")
let http = require("./ajax")
const {JsonResult} = require("./JsonResult");


let runStory = async (apiStory) => {


    for (var i = 0, len = apiStory.apis.length; i < len; i++) {
        await runApi(apiStory, i);
    }

    return JsonResult.of();
}


let getParameterScriptValue = (script, story, apiIndex) => {

    return eval(`
        (function (apis, prevApi, jv) {
            ${script.includes("\n") ? script : ("return " + script)}
        })`)
        .call(story, story.apis, story.apis[apiIndex - 1], jv);

}

let getParameterMap = (story, apiIndex) => {
    var map = {};
    var api = story.apis[apiIndex];

    api.parameters.forEach(it => {
        if (it.script) {
            it.value = getParameterScriptValue(
                it.script,
                story,
                apiIndex
            )
        }

        if (!it.value) {
            return
        }

        map[it.key] = it.value;
    });

    return map;
}

let invokeFirstRequest = (apiStory, apiIndex, interceptor) => {
    if (!interceptor.firstScript) {
        return;
    }

    var api = apiStory.apis[apiIndex];
    var js = `
        (function (story, api, globalHeaders, jv) {
            ${interceptor.firstScript}
        })`

    try {
        eval(js).call(apiStory, apiStory, api, interceptor.globalHeaders, jv);
    }catch(e){
        logger.error(`执行js出错, storyId:${apiStory._id.toString()}, js内容：\n ${js}` )
        throw e;
    }
}

let invokePreRequest = (apiStory, apiIndex, interceptor) => {
    if (!interceptor.requestScript) {
        return;
    }

    var api = apiStory.apis[apiIndex];

    var js = `
        (function (story, api, globalHeaders, jv) {
            ${interceptor.requestScript}
        })`

    try {
        eval(js).call(apiStory, apiStory, api, interceptor.globalHeaders, jv);
    }catch(e){
        logger.error(`执行js出错, storyId:${apiStory._id.toString()}, js内容：\n ${js}` )
        throw e;
    }
}

let invokePostRequest = (apiStory, apiIndex, interceptor) => {
    if (!interceptor.responseScript) {
        return;
    }

    var api = apiStory.apis[apiIndex];

    var js = `
        (function (story, api, globalHeaders, jv) {
            ${interceptor.responseScript}
        })`

    try {
        eval(js).call(apiStory, apiStory, api, interceptor.globalHeaders, jv);
    }catch(e){
        logger.error(`执行js出错, storyId:${apiStory._id.toString()}, js内容：\n ${js}` )
        throw e;
    }
}

let getRequestUrl = (apiStory, apiIndex, parameterMap) => {
    var api = apiStory.apis[apiIndex];
    var url = apiStory.apiAddress + api.apiDefine.url;


    url = url.format(parameterMap, null, it => encodeURIComponent(it));

    if (!url.endsWith("?")) {
        url += "?"
    }

    url += api.apiDefine.requestUrlQueryParameters.map(it => {
        var v = parameterMap[it.key] || it.defaultValue

        if (!v) {
            return ""
        }

        return it.key + "=" + encodeURIComponent(v)
    }).join("&")

    return url;
}


let runApi = async (apiStory, apiIndex) => {
    var interceptors = await mor.find("apiInterceptor", {"isActive": true}, 0, 15);
    //仅处理前面的api
    for(let index = 0; index < apiIndex; index++){
        var api = apiStory.apis[index];
        if (api.status.Between(200, 399) && api.responseBody) {
            try {
                api.responseJson = JSON.parse(api.responseBody);
            } catch (e) {
                logger.error(e.message);
                logger.error("JSON反序列化出错: " + api.responseBody);
            }
        }
    }

    var apiInstance = apiStory.apis[apiIndex];
    var apiStoryBak = JSON.parse(JSON.stringify(apiStory));

    var parameterMap = getParameterMap(apiStory, apiIndex);


    interceptors.forEach(it => {
        invokeFirstRequest(apiStory, apiIndex, it);
    });


    var url = getRequestUrl(apiStory, apiIndex, parameterMap);


    var headers = {};
    apiInstance.apiDefine.requestHeaderParameters.forEach(it => {
        var v = parameterMap[it.key] || it.defaultValue
        if (!v) {
            return
        }
        headers[it.key] = v;
    });


    if (apiInstance.postBodyScript) {
        apiInstance.postBody = getParameterScriptValue(
            apiInstance.postBodyScript,
            this,
            this.apis.indexOf(apiInstance)
        );
    }

    if (apiInstance.postBody) {
        if (apiInstance.apiDefine.requestBodyParameters.items.length) {
            headers["Content-Type"] = "application/json";
        }
    }

    interceptors.forEach(it => {
        invokePreRequest(apiStory, apiIndex, it);
    });



    var res ;
    try {
       res = await http.net(apiInstance.apiDefine.httpMethod, url, apiInstance.postBody, headers);
    }
    catch(e){
        res = e;
    }

    apiInstance.status = res.status;
    apiInstance.responseHeader = res.headers
    apiInstance.responseBody = res.body
    if (res.body && res.contentType.includes("json") ) {
        apiInstance.responseBody = JSON.stringify(JSON.parse(res.body), "", "\t");
    }

    apiInstance.lastExecuteAt = new Date()

    interceptors.forEach(it => {
        invokePostRequest(apiStory, apiIndex, it);
    });

    interceptors.forEachAsync(async interceptor => {
        await mor.update("apiInterceptor",
            {_id: interceptor.id},
            {"globalHeaders": interceptor.globalHeaders})
        ;
    });

    apiInstance.apiDefine = apiStoryBak.apis[apiIndex].apiDefine;


    //仅更新当前api。
    var set = {};
    set[("apis." + apiIndex)] = apiStory.apis[apiIndex];
    var ret = await mor.update("apiStory", {_id: apiStory._id}, set);
    if (ret != 1) {
        logger.error("更新 apiStory 不成功 : " + apiStory._id.toString())
    }
}



let execOriApi = async (method, url, headers,postJson) => {
    return  await http.net(method, url, postJson, headers);
}

module.exports.runApi = runApi;
module.exports.runStory = runStory;
module.exports.execOriApi = execOriApi;
